using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace cosoware.MSBuildTasks.Subversion
{
    /// <summary>
    /// Base class for subversion tool based tasks with xml output.
    /// </summary>
    public abstract class SvnXmlTask : SvnTask
    {
        /// <summary>
        /// String builder that collects output.
        /// </summary>
        private readonly StringBuilder _output = new StringBuilder();

        /// <summary>
        /// Xml representation of output.
        /// </summary>
        private XmlDocument _document;

        /// <summary>
        /// Initializes a new instance of the <see cref="SvnXmlTask"/> class.
        /// </summary>
        public SvnXmlTask()
        {
        }

        /// <summary>
        /// Gets the XML output.
        /// </summary>
        /// <value>The XML output.</value>
        [Output]
        public ITaskItem Xml
        {
            get { return GetOutputTaskItem("Xml"); }
        }


        /// <summary>
        /// Builds the parameters command line.
        /// </summary>
        protected override void BuildCommandLine()
        {
            AppendSwitch("--xml");
        }

        /// <summary>
        /// Logs the events from text output.
        /// </summary>
        /// <param name="singleLine">The single line.</param>
        /// <param name="messageImportance">The message importance.</param>
        protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
        {
            _output.AppendLine(singleLine);
            base.LogEventsFromTextOutput(singleLine, messageImportance);
        }

        /// <summary>
        /// Runs after execute.
        /// </summary>
        /// <returns></returns>
        protected override bool AfterExecute()
        {
            if (!base.AfterExecute())
                return false;
            _document = new XmlDocument();
            _document.LoadXml(_output.ToString());
            RegisterOutputTaskItem("Xml", new TaskItem(_output.ToString()));
            return true;
        }

        /// <summary>
        /// Creates task item from XML node.
        /// </summary>
        /// <param name="key">The key of the task item.</param>
        /// <param name="xpath">The path to the source node.</param>
        /// <returns>Initialized task.</returns>
        protected void CreateOutputFromXmlNode(string key, string xpath)
        {
            CreateOutputFromXmlNode(key, xpath, false);
        }

        /// <summary>
        /// Creates task item from XML node.
        /// </summary>
        /// <param name="key">The key of the task item.</param>
        /// <param name="xpath">The path to the source node.</param>
        /// <param name="required">The node value is required if set to <c>true</c>.</param>
        /// <returns>Initialized task.</returns>
        protected void CreateOutputFromXmlNode(string key, string xpath, bool required)
        {
            Log.LogMessageFromText(String.Format("Get '{0}' from {1}", key, xpath), MessageImportance.Low);
            ITaskItem item = null;
            XmlNode node = _document.SelectSingleNode(xpath);
            if (node == null && required)
            {
                throw new SvnTaskException(String.Format("Can not create '{0}' output task item from xml.", key));
            }
            else if (node == null)
            {
                item = new TaskItem();
            }
            else
            {
                item = new TaskItem(node.InnerText);
            }
            RegisterOutputTaskItem(key, item);
        }
    }
}
